package com.moneycollect.webspider.atome;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.fasterxml.jackson.core.type.TypeReference;
import com.moneycollect.webspider.atome.entity.BrandResponse;
import com.moneycollect.webspider.atome.entity.CommonRS;
import com.moneycollect.webspider.atome.entity.ContactEntity;
import com.moneycollect.webspider.atome.entity.ExportEntity;
import com.moneycollect.webspider.common.*;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.util.CollectionUtils;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @author xuhuiqian
 * @since 2021/12/6 11:59
 */
public class AtomeSpider {

    public static void run() {
        /*try {
            // 获取所有品牌的网站地址
            getCdpAllBrandList();
        } catch (Exception e) {
            e.printStackTrace();
        }*/

        /*try {
            // 获取所有品牌的联系URL
            getContact();
        } catch (Exception e) {
            e.printStackTrace();
        }*/

       /* try {
            // 从联系URL中分析出电话和邮箱
            getContactContent();
        } catch (Exception e) {
            e.printStackTrace();
        }*/

        try {
            // 去重导出
            filterResult();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void filterResult() throws Exception {
        var bankJson = FileHelper.readAllFile4Utf8("E:\\brand3.txt");
        var brandList = JsonUtil.parseObject(bankJson, BrandResponse.class);
        if (brandList != null && !CollectionUtils.isEmpty(brandList.getContainers())) {
            for (var type : brandList.getContainers()) {
                for (var b : type.getMerchantBrands()) {
                    HandlerContact.filterEmail(b);
                    HandlerContact.filterPhone(b);
                }
            }
        }

        var result = JsonUtil.toJson(brandList);
        FileHelper.saveFile(result, "E:\\brand4.txt");

        exportData(brandList);
    }

    private static void exportData(BrandResponse brandList) {
        List<ExportEntity> exportData = new ArrayList<>();

        if (brandList != null && !CollectionUtils.isEmpty(brandList.getContainers())) {
            for (var type : brandList.getContainers()) {
                for (var b : type.getMerchantBrands()) {
                    if(!CollectionUtils.isEmpty(b.getPhone()) || !CollectionUtils.isEmpty(b.getEmail())) {
                        ExportEntity exportEntity = new ExportEntity();
                        exportEntity.setCategory(type.getTitle());
                        exportEntity.setDisplayName(b.getDisplayName());
                        exportEntity.setWebSiteUrl(b.getWebSiteUrl());
                        exportEntity.setContactUsUrl(b.getContactUsUrl());
                        exportEntity.setEmail(b.getEmail());
                        exportEntity.setPhone(b.getPhone());
                        exportData.add(exportEntity);
                    }
                }
            }
        }

        String path = "E:\\brandContact.xls";
        ExcelWriter excelWriter = EasyExcel.write(path, ExportEntity.class)
                .registerConverter(new EasyExcelListConvertor())
                .build();
        WriteSheet sheet = EasyExcel.writerSheet("联系方式").build();
        excelWriter.write(exportData, sheet);
        // 关闭
        excelWriter.finish();
    }

    // region 从联系页面分析联系方式
    private static void getContactContent() throws Exception {
        var bankJson = FileHelper.readAllFile4Utf8("E:\\brand2.txt");
        var brandList = JsonUtil.parseObject(bankJson, BrandResponse.class);

        if (brandList != null && !CollectionUtils.isEmpty(brandList.getContainers())) {
            for (var type : brandList.getContainers()) {
                for (var b : type.getMerchantBrands()) {
                    if (StringUtils.isBlank(b.getContactUsUrl())) {
                        continue;
                    }

                    var fixUrl = fixUrl(b.getWebSiteUrl(), b.getContactUsUrl());
                    if (StringUtils.isBlank(fixUrl) || !fixUrl.toLowerCase().startsWith("http")) {
                        continue;
                    }

                    extractContactContent(b, fixUrl, null);
                    System.out.println("[" + type.getReference() + "][" + b.getReference() + "]get contract content");
                }
            }

        }

        var result = JsonUtil.toJson(brandList);
        FileHelper.saveFile(result, "E:\\brand3.txt");
    }

    private static String fixUrl(String webSiteUrl, String contactUsUrl) {
        if (contactUsUrl.toLowerCase().startsWith("http")) {
            return contactUsUrl;
        }

        if (contactUsUrl.toLowerCase().startsWith("mailto")) {
            return null;
        }

        var root = StringUtils.stripEnd(webSiteUrl, "/");
        var relatedUrl = StringUtils.stripStart(contactUsUrl, "/");
        return root + "/" + relatedUrl;
    }

    private static void extractContactContent(BrandResponse.Brand b, String url, String content) {
        ContactEntity contactUsEntity = null;
        if (StringUtils.isNotBlank(content)) {
            contactUsEntity = HandlerContact.getContactContent(content);
        } else if(StringUtils.isNotBlank(url)) {
            String htmlContent = GetHtmlHelper.getHomePageContentByHttpClient(url);
            contactUsEntity = HandlerContact.getContactContent(htmlContent);
            if (CollectionUtils.isEmpty(contactUsEntity.getEmail()) && CollectionUtils.isEmpty(contactUsEntity.getPhone())) {
                htmlContent = GetHtmlHelper.getUrlHtmlContentByCdp(url);
                contactUsEntity = HandlerContact.getContactContent(htmlContent);
            }
        }

        if (b.getEmail() == null) {
            b.setEmail(new ArrayList<>());
        }
        if (b.getPhone() == null) {
            b.setPhone(new ArrayList<>());
        }

        if(contactUsEntity != null && contactUsEntity.getEmail() != null) {
            b.getEmail().addAll(contactUsEntity.getEmail());
        }

        if(contactUsEntity != null && contactUsEntity.getPhone() != null){
            b.getPhone().addAll(contactUsEntity.getPhone());
        }
    }

    // endregion

    // region 获取商家联系页面的URL
    private static final Pattern contactUsPattern = Pattern.compile("(聯繫我們|联系我们|聯絡我們|联络我们|Contact Us|联络)+");

    private static void getContact() throws Exception {
        var bankJson = FileHelper.readAllFile4Utf8("E:\\brand.txt");
        var brandList = JsonUtil.parseObject(bankJson, BrandResponse.class);

        if (brandList != null && !CollectionUtils.isEmpty(brandList.getContainers())) {
            for (var type : brandList.getContainers()) {
                for (var b : type.getMerchantBrands()) {
                    if (StringUtils.isBlank(b.getWebSiteUrl()) || StringUtils.isNotBlank(b.getContactUsUrl())) {
                        continue;
                    }

                    String contactUsUrl = null;
                    var requestUrl = b.getWebSiteUrl();

                    var htmlContent = GetHtmlHelper.getHomePageContentByHttpClient(requestUrl);
                    contactUsUrl = searchContactUsUrl(htmlContent);
                    if (StringUtils.isBlank(contactUsUrl)) {
                        htmlContent = GetHtmlHelper.getUrlHtmlContentByCdp(requestUrl);
                        contactUsUrl = searchContactUsUrl(htmlContent);
                    }

                    b.setContactUsUrl(contactUsUrl);
                    System.out.println("[" + type.getReference() + "][" + b.getReference() + "]get contract url");

                    // 随便分析首页上是否有联系方式
                    extractContactContent(b, null, htmlContent);
                    System.out.println("[" + type.getReference() + "][" + b.getReference() + "]get contract url--getContact");
                }
            }

        }

        var result = JsonUtil.toJson(brandList);
        FileHelper.saveFile(result, "E:\\brand2.txt");
    }

    private static String searchContactUsUrl(String htmlDoc) {
        if (StringUtils.isBlank(htmlDoc)) {
            return null;
        }
        try {
            Document doc = Jsoup.parseBodyFragment(htmlDoc);
            var allElement = doc.getElementsMatchingText(contactUsPattern);
            if (allElement.size() > 0) {
                for (org.jsoup.nodes.Element element : allElement) {
                    var href = element.attr("href");
                    if (StringUtils.isNotBlank(href)) {
                        return href;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // endregion

    // region 获取品牌网站URL
    private static void getCdpAllBrandList() throws Exception {
        HttpClient httpClient = HttpClient.newBuilder()
                .connectTimeout(Duration.of(60, ChronoUnit.SECONDS))
                .build();

        URI uri = new URI("https://www.atome.hk/api/content-operation/pages/public?type=WEBSITE_MERCHANT_BRAND");
        HttpRequest request = HttpRequest.newBuilder()
                .GET()
                .uri(uri)
                .header("accept", "application/json")
                .header("referer", "https://www.atome.hk/paylater-stores/women")
                .header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36")
                .header("cookie", "_atome_webAdvertisingId=adf1dee8-8683-43f7-9c8e-74bc67905062; _atome_webDeviceId=160c64c7-a6b5-4255-abf1-5eb894d0c4e0; _gid=GA1.2.453298931.1638177854; _fbp=fb.1.1638177854993.1825348142; _ga=GA1.2.1203463214.1638177854; _gat_UA-163789353-4=1; _ga_7ZBRM1ZKZM=GS1.1.1638183293.2.1.1638185284.0")
                .timeout(Duration.of(120, ChronoUnit.SECONDS))
                .build();

        var rsContent = httpClient.send(request, HttpResponse.BodyHandlers.ofString()).body();
        var rsData = JsonUtil.parseObject(rsContent, new TypeReference<CommonRS<BrandResponse>>() {
        });
        if (rsData == null || rsData.getData() == null) {
            return;
        }

        var brandList = rsData.getData();
        if (brandList != null && !CollectionUtils.isEmpty(brandList.getContainers())) {
            // 删除 ALLSTORE，因为这里面的内容在其它品类里面都包含了
            brandList.getContainers().removeIf(type -> type.getReference().equals("ALLSTORE"));

            for (var type : brandList.getContainers()) {
                for (var b : type.getMerchantBrands()) {
                    var tempUrl = "https://www.atome.hk/paylater-merchants/" + b.getReference();
                    String brandWebSite = null;

                    var htmlContent = GetHtmlHelper.getHomePageContentByHttpClient(tempUrl);
                    brandWebSite = getBrandWebSite(htmlContent);

                    if (StringUtils.isBlank(brandWebSite)) {
                        htmlContent = GetHtmlHelper.getUrlHtmlContentByCdp(tempUrl);
                        brandWebSite = getBrandWebSite(htmlContent);
                    }

                    b.setWebSiteUrl(brandWebSite);
                    System.out.println("[" + type.getReference() + "][" + b.getReference() + "]get root web site");
                }
            }

            var result = JsonUtil.toJson(brandList);
            FileHelper.saveFile(result, "E:\\brand.txt");
        }
    }

    private static String getBrandWebSite(String htmlContent) {
        if (StringUtils.isBlank(htmlContent)) {
            return null;
        }
        try {
            Document doc = Jsoup.parseBodyFragment(htmlContent);
            var elements = doc.getElementsByAttributeValue("class", "btn");
            if (elements.size() > 0) {
                for (org.jsoup.nodes.Element currentElement : elements) {
                    if (currentElement.text().equals("前往商家網站")) {
                        var brandWebSite = currentElement.attr("href");
                        if (StringUtils.isNotBlank(brandWebSite)) {
                            return brandWebSite;
                        }
                    }
                }
            }
        } catch (Exception e) {
            return null;
        }

        return null;
    }

    // endregion

}
